package com.zhuhjay.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * 实体类构建器
 * @author ZhuHJay
 * @date 2023/1/11 13:30
 */
public class BeanBuilder<T> {

    /** 生产者：负责生成需要的实体对象 */
    private final Supplier<T> constructor;
    /** 消费者列表：进行对象属性的注入 */
    private final List<Consumer<T>> dInject = new ArrayList<>();

    private BeanBuilder(Supplier<T> constructor) {
        this.constructor = constructor;
    }

    /**
     * 创建一个建造者
     * @param constructor 生产者，负责创建一个实体对象
     * @param <T> 泛型
     * @return 建造者
     */
    public static <T> BeanBuilder<T> builder(Supplier<T> constructor) {
        return new BeanBuilder<>(constructor);
    }

    /**
     * 传入实体对象的 set 方法，定义消费者来进行属性的注入
     * @param depInjectMethod 类名::setterMethod
     * @param value 值
     * @param <V> 值泛型
     * @return 建造者
     */
    public <V> BeanBuilder<T> with(DepInjectConsumer<T, V> depInjectMethod, V value) {
        // 定义一个消费者，用来调用实例的setter方法修改属性
        /* depInjectMethod.accept(instance, value) ->
            ((T)instant).depInjectMethod(value) : Lambda表达式反编译后的代码 */
        Consumer<T> consumer = instance -> depInjectMethod.accept(instance, value);
        // 添加到列表中，构建时才使用
        dInject.add(consumer);
        return this;
    }

    /**
     * 建造开始，此时才进行属性的注入
     * @return 完成建造的实体实例
     */
    public T build() {
        // 通过生产者获取实例
        T instance = constructor.get();
        // 调用消费者进行属性的依赖注入
        dInject.forEach(dInject -> dInject.accept(instance));
        // 实例构建完成
        return instance;
    }

    @FunctionalInterface
    public interface DepInjectConsumer<T, V> {
        /**
         * 属性注入
         * @param t 类型实例
         * @param v 值
         */
        void accept(T t, V v);
    }
}
